﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace MPSync
{
    class Sync
    {
        public event EventHandler SyncStarted;
        public event EventHandler SyncUpdated;
        public event EventHandler SyncCompleted;

        string mSource;
        string mDest;
        private int mTotalFiles;
        private int mCurrentFileNumber = 0;

        public void SyncStart(string source, string dest)
        {
            mSource = source;
            mDest = dest;

            // Get total files for this sync operation
            string[] allFiles = Directory.GetFiles(mSource, "*.*", SearchOption.AllDirectories);
            mTotalFiles = allFiles.Count();

            ThreadPool.QueueUserWorkItem(ThreadStart);
        }

        private void ThreadStart(object obj)
        {
            SyncStarted(this, new SyncEventArgs(mSource,0,0));
            Backup(mSource, mDest);
            SyncCompleted(this, new SyncEventArgs(mSource,0,0));
        }

        private void Backup(string src, string dst)
        {
            try
            {
                string[] files;

                // Check trailing directory seperator exists
                if (dst[mDest.Length - 1] != Path.DirectorySeparatorChar)
                {
                    dst += Path.DirectorySeparatorChar;
                }

                // Check destination directory exists
                if (!Directory.Exists(dst))
                {
                    Directory.CreateDirectory(dst);
                }

                files = Directory.GetFileSystemEntries(src);

                foreach (string element in files)
                {
                    // Check if the element is a directory which already exists
                    if (Directory.Exists(element))
                    {
                        Backup(element, dst + Path.GetFileName(element));
                    }
                    else
                    {
                        string dstFile = dst + Path.GetFileName(element);
                        string srcFile = Path.GetFullPath(element);

                        FileInfo dstFI = new FileInfo(dstFile);
                        FileInfo srcFI = new FileInfo(srcFile);

                        if (dstFI.Exists)
                        {
                            try
                            {
                                if (dstFI.LastWriteTimeUtc < srcFI.LastWriteTimeUtc)
                                {
                                    File.Copy(element, dst + Path.GetFileName(element), true);
                                    string updateText = "Update: " + Path.GetFileName(element) + " -> " + dst;
                                    SyncUpdated(this, new SyncEventArgs(updateText, mCurrentFileNumber, mTotalFiles));
                                }
                                else
                                {
                                }
                            }
                            catch (System.IO.IOException e)
                            {
                                string errorText = "File In Use Error: " + Path.GetFileName(element) + " -> " + dst;
                                SyncUpdated(this, new SyncEventArgs(errorText, mCurrentFileNumber, mTotalFiles));
                            }
                        }
                        else
                        {
                            try
                            {
                                File.Copy(element, dst + Path.GetFileName(element), true);
                                string updateText = "Update: " + Path.GetFileName(element) + " -> " + dst;
                                SyncUpdated(this, new SyncEventArgs(updateText, mCurrentFileNumber, mTotalFiles));
                            }
                            catch (System.IO.IOException e)
                            {
                                string errorText = "File In Use Error: " + Path.GetFileName(element) + " -> " + dst;
                                SyncUpdated(this, new SyncEventArgs(errorText, mCurrentFileNumber, mTotalFiles));
                            }
                        }
                    }
                    mCurrentFileNumber++;
                }
            }
            catch (System.IO.DirectoryNotFoundException e)
            {
            }
        }
    }
}
